package gologv0

import (
	"fmt"
	"gitee.com/ymofen/gobase/subpub"
	"runtime"
	"sync"
	"time"
)

type GoLogRecord struct {
	Level       int8      // The log level
	CreatedTime time.Time // The time at which the log message was created (nanoseconds)
	Source      string    // The message source
	Typestr     string    // typestr
	Msg         interface{}
}

type GoLog struct {
	disp    subpub.ISubPub
	recPool sync.Pool
}

func NewGoLog() *GoLog {
	rval := &GoLog{}
	rval.init()
	return rval
}

func (this *GoLog) getLogRecord() *GoLogRecord {
	rec := this.recPool.Get().(*GoLogRecord)
	return rec
}

var (
	defGoLog = NewGoLog()
)

/*
id: 唯一, typestr下id是唯一的, 重复添加会覆盖id的上一次回调
typestr : * 代表所有
*/
func (this *GoLog) AddLogger(id string, typestr string, onMsg func(rec *GoLogRecord) bool) {
	this.disp.Sub(id, typestr, func(id, topic string, args ...interface{}) (ok bool) {
		return onMsg(args[0].(*GoLogRecord))
	})
}

/*
typestr 是add时, 传入的typestr
*/
func (this *GoLog) DelLogger(id string, typestr string) {
	this.disp.Unsub(id, typestr)
}

func (this *GoLog) init() {
	this.disp = subpub.NewSubchannel()
	this.recPool.New = func() any {
		return &GoLogRecord{}
	}
}

func (this *GoLog) LogMsg(typestr string, lvl int8, callskip int, msg interface{}) {
	pc, _, lineno, ok := runtime.Caller(callskip + 1)
	rec := this.getLogRecord()
	defer this.recPool.Put(rec)
	if ok {
		rec.Source = fmt.Sprintf("%s:%d", runtime.FuncForPC(pc).Name(), lineno)
	} else {
		rec.Source = ""
	}
	rec.Level = lvl
	rec.Typestr = typestr
	rec.Msg = msg
	rec.CreatedTime = time.Now()
	this.disp.Pub(typestr, 0, rec)
}

func (this *GoLog) LogMsgf(typestr string, lvl int8, callskip int, s string, args ...interface{}) {
	msg := s
	if len(msg) == 0 {
		msg = fmt.Sprint(args...)
	} else {
		if len(args) > 0 {
			msg = fmt.Sprintf(s, args...)
		}
	}

	this.LogMsg(typestr, lvl, callskip+1, msg)
}

func Log3Msgf(callskip int, s string, args ...interface{}) {
	defGoLog.LogMsgf("", 0, callskip+1, s, args...)
}

func LogMsgf(typestr string, lvl int8, callskip int, s string, args ...interface{}) {
	defGoLog.LogMsgf(typestr, lvl, callskip+1, s, args...)
}

func LogMsg(typestr string, lvl int8, callskip int, msg interface{}) {
	defGoLog.LogMsg(typestr, lvl, callskip+1, msg)
}

// 回调中onMsg函数中rec参数不能进行异步使用
func AddLogger(id string, typestr string, onMsg func(rec *GoLogRecord) bool) {
	defGoLog.AddLogger(id, typestr, onMsg)
}

/*
typestr 是add时, 传入的typestr
*/
func DelLogger(id string, typestr string) {
	defGoLog.DelLogger(id, typestr)
}
